Глава 16

Рассылка и получение почты

Служба электронной почты настолько привычна сегодня, что многие просто не представляют, какой была бы жизнь в отсутствие этого полезного и неприхотливого способа связи. По заявлениям в Internet первое электронное письмо в мире было отправлено в 1971 году при тестировании нового, только что разработанного способа передачи текстовой информации между двумя компьютерами. Что касается содержания первого электронного письма, то остается только догадываться, каким оно было. Впрочем, это не столь важно. Главное, что такое событие позволило открыть еще один способ общения между людьми.

Существует множество программ, позволяющих "прогрессивному" сообществу общаться между собой. Здесь могут быть использованы любые технологии — от систем обмена сообщениями типа ICQ до видеоконференций. Несмотря на это, сегодня, как и на заре развития Internet, самым распространенным и наиболее надежным способом сообщить что-либо другому человеку или переслать файл остается электронная почта (e-mail).

Для работы с почтой можно использовать специализированную программу — почтовый клиент, или же зарегистрироваться в системе Web-почты и оперировать с почтой через браузер. Если пользователь ведет активную переписку, то второй способ практически неприменим: требования к почтовой программе для активных пользователей весьма высоки. ColdFusion в свою очередь позволяет оперировать почтой с помощью тегов <CFMAIL> и <CFPOP>, которые предназначены для отправления и получения почты соответственно.

Teг<CFMAIL>

Синтаксис:

<CFMAIL TO = "recipient" FROM = "sender"

СС = "copy_to" ВСС = "blind_copy_to"

SUBJECT = "msg_subject" TYPE = "msg_type"

MAXROWS = "maxjnsgs" MIMEATTACH - "path"

QUERY = "query_name" GROUP = "query_column"

GROUPCASESENSITIVE = "Yes |No"

STARTROW = "query_row" SERVER = "servername"

PORT = "port_ID" MAILERID = "headerid"

TIMEOUT = "seconds"> Содержание письма </CFMAIL>

В табл. 16.1 представлено описание атрибутов тега <CFMAIL>.

Таблица 16.1. Описание атрибутов тега <CFMAIL>

Атрибут

Описание

то

Электронный адрес получателя. Обязательный атрибут

FROM

Электронный адрес отправителя. Обязательный атрибут

СС

Электронный адрес для копии отправляемого письма. Необязательный атрибут1

BCC

Электронный адрес для копии отправляемого письма без внесения в список писем. Необязательный атрибут2

SUBJECT

Тема письма. Обязательный атрибут

TYPE


Тип письма. В этой связи может быть использовано значе-

ние HTML. Этот атрибут полезен в случае отправления письма в HTML-формате. Необязательный атрибут

MAXROWS

Максимальное количество отправляемых писем. Используется вместе с атрибутом QUERY. Необязательный атрибут

MIMEATTACH

Файл, прилагаемый к письму, с указанием полного пути. Необязательный атрибут

QUERY

Наименование запроса. Используется для рассылки нескольких писем или для отправления результата запроса. Необязательный атрибут

 

Атрибут

Описание

GROUP

Наименование колонки запроса. Используется вместе с атрибутом QUERY для группировки отправляемых писем по заданной колонке запроса. Необязательный атрибут

GROUPCASESENSITIVE

Восприимчивость к регистру. Используется для указания учета регистра при группировке результата запроса. Возможные значения:

• Yes — да (по умолчанию); • NO — нет.

Необязательный атрибут

STARTROW

Номер записи, с которой следует посылать письма. Указывается вместе с атрибутом QUERY. Необязательный атрибут

SERVER

Адрес SMTP-сервера, используемый для рассылки писем. Если данный атрибут не задан, используется значение, указанное на странице "ColdFusion Administrator". Обязательный атрибут

PORT

TCP/IP-порт, используемый SMTP-сервером. Обычно принимает значение 25. Необязательный атрибут

MAILERID

Идентификатор отправителя, в заголовке получаемого письма значится как X-mailer. Необязательный атрибут

TIMEOUT

Период ожидания для соединения с SMTP-сервером. Измеряется в секундах. Необязательный атрибут

 

Рассылка почты

Теперь, когда у вас уже есть представление о возможных атрибутах тега <CFMAIL>, позволяющего отправлять почтовые сообщения, можно перейти к примерам. И в качестве одного из первых примеров приведем код, демонстрирующий отправление электронного письма, используя обязательные атрибуты:

<CFMAIL TO="Anna@MyMail"

FROM="Ruben@MyMai1" SUBJECT="Hello Anjuta"

SERVER="192.168.3.68"> This message was sent by an

automatic mailer built with CFMAIL </CFMAIL>

где в качестве SMTP-сервера указан IP-адрес компьютера с предустановленным специализированным программным продуктом. Впрочем, при реализации приложения можно использовать заранее объявленные переменные, как показано в следующем примере:

<HTML> <HEAD>

<TITLE>MyCFMail.cfm</TITLE> </HEAD> <BODY>

<CFIF isDefined("Form.To")> <CFMAIL TO = #Form.To#

FROM = #Form.From# SUBJECT = fForm.Subject*

SERVER = #Application.smtp#> #Form.Body# </CFMAIL> <CFELSE>

<FORM act±on="MyCFMail.cfm" method="post" name="forml">

<TABLE width="400" border="0" cellspacing="4" cellpadding="0">

<TR><TD align="right">From</td>

<TD><input name="From" size="20"></TD></TR>

<TR><TD align="right">To</td>

<TD><input name="To" size="20"></TD></TR>

<TR><TD align="right">Subject</td>

<TD><input name="Subject" size="40"></TD></TR>

<TR><TD colspan="2">

<textarea name="Body" rows="10" cols="70"></textarea> </TD></TR>

<TR><TD align="right"><input type="submit" value="Send"></TD>

<TD><input type="reset" value="Clear"> </TD></TR>

</TABLE> </FORM> </CFIF> </BODY> </HTML>

Здесь переменная приложения Application.smtp объявляется в конфигурационном файле приложения Application.cfm, остальные же значения передаются из заранее подготовленной формы, отраженной в этом же примере.

Если же следует отправлять письма в виде HTML, то необходимо использовать атрибут TYPE, как показано ниже:

<CFMAIL TO="Anna@MyMail"

FROM="Ruben@MyMail" SUBJECT="Hello Anjuta" TYPE="HTML"

SERVER="192.168.3.68"> <hl>Hello Anjuta</hl> <FONT color="Maroon"

face="Bookman Old Style">

How are you? </FONT> </CFMAIL>

Как видно из описания тега <CFMAIL>, для вложения файла в отправляемое письмо необходимо использовать атрибут MIMEATTACH. Однако вложение файлов также можно осуществлять, используя тег <CFMAILPARAM>, который в свою очередь должен быть помещен внутрь тега <CFMAIL>. Причем для вложения файла с использованием тега <CFMAILPARAM> необходимо указывать атрибут FILE, как показано в следующем примере:

<CFMAIL TO="Anna@MyMail"

FROM="Ruben@MyMail"

SUBJECT="Hello Anjuta"

SERVER="192.168.3.68"

MIMEATTACH="c:\temp\file1.doc"> Hello Anjuta Send you three files.

<CFMAILPARAM FILE="c:\temp\file2.doc">

<CFMAILPARAM FILE="c:\temp\file3.htm"> </CFMAIL>

Здесь к письму прикладывается три файла, вложение двух из которых осуществляется посредством тега <CFMAILPARAM>, который можно использовать в одном письме более одного раза. Тег <CFMAILPARAM> также можно применять для встраивания в заголовок письма дополнительных параметров, как показано ниже:

<CFMAIL TO="Anna@MyMail"

FROM="Ruben@MyMail" SUBJECT="Hello Anjuta"

SERVER="192.168.3.68"> Hello Ahjuta

<CFMAILPARAM NAME="Gratitude" VALUE="For Anjuta"> Thank you for all. </CFMAIL>

где с помощью атрибута NAME в заголовок письма был включен параметр с именем "Gratitude", а в качестве значения этого параметра было задано значение "For Anjuta" с помощью атрибута VALUE тега <CFMAILPARAM>.

Следующий пример демонстрирует возможность рассылки писем с использованием базы данных:

<HTML> <HEAD>

<TITLE>Seasonal dispatch</TITLE> </HEAD> <BODY>

<CFQUERY NAME="GetTraveler" DATASOURCE="#application.dsn#"> SELECT *

FROM Traveler

ORDER BY FirstName_tra, LastName_tra </CFQUERY>

<CFMAIL TO = #EMail_tra#

FROM="Root@MyMail" SUBJECT="Change of the schedule" SERVER="192.168.3.68" QUERY="GetTraveler"> Dear #FirstName_tra#

The schedule of cruises has been changed due to the coming of the new season. </CFMAIL>

</BODY> </HTML>

В приведенном выше примере предварительно был сформирован запрос с именем "GetTraveier", в последствии указанный в теге <CFMAIL>. В результате чего всем зарегистрированным любителям путешествовать будет отправлено уведомление об изменении расписания круизов в связи с переходом на новый сезон.

Ограничение же по рассылке уведомлений можно устанавливать как изменением непосредственно формы запроса, добавляя необходимые критерии, так и с использованием необязательного атрибута MAXROWS, позволяющего установить максимальное количество отправляемых писем независимо от результата запроса.

Ter<CFPOP>

Синтаксис:

<CFPOP SERVER = "servername" PORT = "port_number"

USERNAME = "username" PASSWORD = "password"

ACTION = "GetHeaderOnly | GetAll | Delete" NAME = "queryname"

MESSAGENUMBER = "number" ATTACHMENTPATH = "path"

TIMEOUT = "seconds" MAXROWS = "number" STARTROW = "number"

GENERATEUNIQUEFILENAMES = "Yes | No">

В табл. 16.2 представлено описание атрибутов тега <CFPOP>.

Таблица 16.2. Описание атрибутов тега <CFPOP>

Атрибут

Описание

SERVER PORT USERNAME

PASSWORD ACTION

Адрес POP-сервера, используемый для получения писем. Обязательный атрибут

Порт, используемый POP-сервером. Обычно принимает значение 110. Необязательный атрибут

Учетная запись пользователя. При отсутствии указания пользователя связь приобретает анонимный характер (anonymous). Необязательный атрибут

Пароль пользователя. Необязательный атрибут

Определение действия по отношению к входящим письмам. Возможные значения:

  • GetHeaderOnly— возвращает частичную информацию, не включая вложенные файлы, содержание и подробный заголовок входящего письма (по умолчанию);
  • GetAll — возвращает всю информацию; • Delete — удаляет входящее письмо на РОР-сервере

 

Атрибут

Описание

NAME

Имя формирующегося запроса на основании полученных писем. Обязательный атрибут для таких действий, как

GetHeaderOnly и GetAll

MESSAGENUMBER

Порядковый номер входящего письма. Обязательный атрибут для действия удаления Delete. Также можно использовать для действий GetHeaderOnly и GetAll в целях получения только определенных писем. Причем в качестве порядкового номера можно указывать несколько писем через запятую. Несуществующие письма игнорируются

ATTACHMENT PATH

Месторасположение вложенных файлов. Может использоваться в сочетании с действием GetAll. Необязательный атрибут

TIMEOUT

Период ожидания для обработки писем. По умолчанию 60 секунд. Необязательный атрибут

MAXROWS

Максимальное количество входящих писем. Игнорируется в случае использования атрибута MESSAGENUMBER. Необязательный атрибут

STARTROW

Номер записи, с которой следует обрабатывать письма. По умолчанию равен 1. Игнорируется в случае использования атрибута MESSAGENUMBER. Необязательный атрибут

GENERATEUNIQUEFILE NAMES

Индикатор, указывающий на создание уникальных имен для вложенных файлов, имеющих* одинаковые имена с уже существующими размещенными файлами. Возможные значения:

• Yes —да; • No — нет (по умолчанию). Необязательный атрибут

При использовании тега <CFPOP> создается объект запроса, обеспечивающий доступ к вспомогательной информации с помощью следующих переменных:

При определении действия GetHeaderOnly в объект запроса включаются следующие колонки:

При определении действия Get АИ помимо вышеперечисленных колонок в объект запроса включаются также такие колонки, как:

Список как вложенных файлов, так и их путей перечисляется через восьмибитовый расширенный ASCII-код CHR (9) (знак табуляции).

Получение почты

Предположим, что нам необходимо вывести основные данные по полученным электронным сообщениям для конкретного пользователя с предварительным отражением количества принятых писем на РОР-сервере:

<HTML> <HEAD>

<TITLE>CFPOP</TITLE> </HEAD> <BODY>

<CFPOP SERVER = "192.168.3.68"

USERNAME = "Anna" PASSWORD = "******" NAME = "GetMail"

ACTION="GetHeaderOnly">

<h3>Your Inbox: <CFOUTPUT>#GetMail.RecordCount#</CFOUTPUT></h3>

<TABLE border="l" cellpadding="2" cellspacing="2"> <TR>

<TD>Row</TD><TD>To</TD><TD>From</TD>

<TD>SUBJECT</TD> <TD>Date</TD> </TR>

<CFOUTPUT QUERY="GetMail">

<TR> <TD>#CurrentRow#</TDXTD>#To#</TDXTD>#From#</TD>

<TD>#Subject#</TD>

<TD>#DateFormat(ParseDateTime(Date), "dd/mm/yyyy")#</TD>

</TR>

</CFOUTPUT> </TABLE>

</BODY> </HTML>

Здесь для вывода такой информации, как текущая запись, электронный адрес получателя, электронный адрес отправителя, тема входящего письма и дата размещения в почтовом ящике используется уже знакомый тег <CFOUTPUT> с атрибутом QUERY, указывающим на имя запроса. Заметим, что для преобразования текстового отображения даты в объект формата "дата/время" следует использовать функцию ParseDateTime, как показано в приведенном примере.

Достаточно часто вместе с почтовыми сообщениями передаются различные файлы, такие файлы мы называем вложенньми или прикрепленными к письму. Причем к одному входящему почтовому сообщению может быть прикреплено сразу несколько файлов. В свою очередь тег <CFPOP> располагает таким атрибутом, как ATTACHMENTPATH, позволяющим устанавливать месторасположение вложенных файлов, а переменная attachmentFiies получаемого запроса в результате использования тега <CFPOP> принимает значение списка путей вложенных файлов. В этой связи в качестве следующего примера продемонстрируем возможность считывания вложенных файлов, не забывая, что для успешного использования переменной attachmentFiles необходимо указывать действие ACTION, равное "GetAll":

<CFPOP SERVER = "192.168.3.68" USERNAME = "Anna"

PASSWORD = "******" NAME = "GetMailAttach"

MESSAGENUMBER="2"

ATTACHMENTPATH="c:\temp\my" ACTION="GetAll">

<CFOUTPUT QUERY="GetMailAttach">

<TABLE border="l" width="400" cellpadding="2" cellspacing="2">

<TR><TD align="right"><b>From: </b></TD>

<TD>#Froml</TD></TR>

<TR><TD align="right"><b>Subject:</b></TD>

<TD>#Subject#</TDX/TR>

<TR><TD colspan="2">#Body#</TDX/TR>

<TR><TD align="right" valign="top"><b>Attachments:</b></TD> <TD>

<CFLOOP INDEX="i" LIST=#AttachmentFiles# DELIMITERS=IChr(9)#>

<a href="file://#i#">#i#</a><br> </CFLOOP> </TD></TR>

</TABLE> </CFOUTPUT>

Здесь атрибут MESSAGENUMBER тега <CFPOP> указывает на порядковый номер входящего письма, которое в последствии является объектом для считывания вложенных файлов.

Еще раз отметим, что список путей вложенных файлов перечисляется через восьмибитовый расширенный ASCII-код CHRO), используемый в нашем случае в качестве разделителя при формировании списка прикрепленных файлов с помощью тега <CFLOOP>.

Для удаления входящих на POP-сервер писем достаточно указать тег <CFPOP> в сочетании с определением действия ACTION, равным "Delete", и указанием порядкового номера письма с помощью атрибута MESSAGENUMBER. Для удаления же сразу нескольких писем можно использовать цикл или в качестве порядкового номера указывать список писем через запятую. Следующий пример демонстрирует удаление входящего письма с порядковым номером 1.

<CFPOP SERVER = "192.168.3.68" USERNAME = "Anna"

PASSWORD = "******" ME S SAGENUMBER="1"

ACTION="Delete" NAME= "DelMail">

Так же, как и с тегом <CFMAIL>, при обработке входящей почты можно применять заранее объявленные переменные, как показано в следующем примере:

<CFPOP SERVER = #ServerPOP#

USERNAME = #Form.UserName# PASSWORD = #Form.Password#

MESSAGENUMBER = #Form.MessNum#

ACTION = "Delete" NAME="DelMail">

Пример реализации почтового ящика

В качестве примера рассмотрим создание собственной почтовой службы на Web-сервере, заранее установив один из почтовых серверов с именем "MyMail".

В первую очередь хотелось бы сформулировать конечную цель, что немаловажно при реализации любого проекта. А задача между тем тривиальна -реализуется возможность читать и отправлять почту с помощью Web-браузера. Далее обсудим детали.

Соответственно с любым приложением, предназначенным для использования различными группами людей, следует включить форму регистрации, которая бы позволила определять уникальный профиль того или иного пользователя. Также необходимо предусмотреть возможность ведения индивидуальной адресной книги каждого пользователя.

С чего начать?

Конечно, очень важно, чтобы система управления электронной почтой была простой и удобной в использовании. Эту задачу каждый программист выполняет по мере своих возможностей и накопленного опыта. Что же касается удобства, то исходя из опыта уже существующих подобных приложений, электронные письма желательно разбивать на тематические разделы или так называемые папки. В этом плане можно было бы создать гибкую систему по управлению папками с возможностью добавления новых и удаления существующих папок. Однако в нашем примере будем довольствоваться набором стандартных разделов. Тем более, что список папок станет храниться в таблице базы данных, и для добавления модуля по управлению папками необходимо будет всего лишь несколько изменить наш код и добавить пару CFML-страниц. Между тем, в качестве стандартных папок будем использовать:

На приведенной схеме помимо модулей показаны выполняемые действия по отношению к базе данных в виде цилиндрических фигур, где:

Для удобства просмотра такие действия, как select (выборка данных) на приведенной принципиальной схеме не показаны.

Процесс же разработки базы данных подробно описан в главе 5 на примере проекта "My-Line Cruises". Так что здесь мы покажем результат окончательной фазы проектирования базы данных MyMail, это так называемая физическая модель, для простоты реализованная под Microsoft Access.

Регистрация

Теперь немного о том, как это работает. Изначально пользователю предлагается заполнить регистрационную карточку (SignUp.cfm), после чего при успешной регистрации на только что созданный почтовый ящик отправляется приветствие с уведомлением о внесенной информации, касающейся данного пользователя (SendPassword.cfm). Затем в окне браузера появляется новое меню с возможностью читать входящую почту (MailBox.cfm), создавать письма для последующей отправки (NewMail.cfm), формировать собственную адресную книгу (Addresses.cfm) и закрывать сессию (LogOut.cfm) для предоставления возможных пауз во время работы с почтовой службой. При этом в дальнейшем для работы с данной службой достаточно будет только пройти идентификацию (Login.cfm), т. е. ввести свой электронный адрес и пароль.

Изменение же пароля возможно в любой момент после идентификации в режиме работы с программой MyMaii, для чего достаточно всего лишь выбрать ссылку с собственным именем, находящуюся на текущей CFML-странице, и произвести необходимые изменения (EditUser.cfm). При смене пароля система принудительно отправляет электронное сообщение о совершенных изменениях (SendPassword.cfm), что отображено на уже рассмотренной схеме.

Шифрование пользовательских паролей

В данном примере реализации почтового ящика мы впервые использовали так называемое шифрование паролей, хранящихся в базе данных. В ColdFusion существуют две функции: Encrypt и Decrypt. Первая из них — Encrypt — позволяет зашифровать текст по определенному алгоритму с помощью назначения ключа. Вторая функция — Decrypt — соответственно позволяет расшифровать полученный результат при использовании того же ключа. Например, при регистрации пользователя можно совершить следующее действие:

<CFSET Password = Encrypt(Form.Pass_User, Session.user.id)>

где Form.Pass_User — введенный пользователем пароль; Session.user.id -уникальный ключ пользователя, присваиваемый на уровне триггера базы данных.

Следующим действием можно произвести обновление пароля для данного пользователя:

<CFQUERY NAME="UpdatePass" DATASOURCE="#Application.dsn#">

UPDATE UserMail

SET Pass_User = '#Password#'

WHERE Key_User = #Session.user.id# </CFQUERY>

Данный пример регистрации (signup.cfm) полностью представлен в листинге П2.7 приложения 2. »

Теперь наш пароль хранится в базе данных в зашифрованном виде. Однако иногда возникает необходимость расшифровать пароль. Скажем, при требовании пользователя передать пароль по электронной почте или при идентификации пользователя в момент очередного посещения почтовой службы следует уже использовать функцию Decrypt. Например:

<CFIF isDefined("URL.EMail")>

<CFQUERY NAME="Verification" DATASOURCE="#Application.dsn#">

SELECT Pass_User, FirstNJJser, EMail_User, KeyJJser FROM UserMail

WHERE EMail_User = '#URL.EMail#' </CFQUERY>

<CFIF Verification.RecordCount eq 1>

<CFSET PostMasterEMail = "Root" & #Application.mailserver#>

<CFSET Password = Decrypt(Verification.Pass_User,

Verification.Key User)>

<!--- Send EMail Password --->

<CFMAIL TO="#URL.EMailtt"

FROM="#PostMasterEMaill"

SUBJECT="Password"

SERVER="#Application.smtp#">

Dear#Verification.FirstN_Userl

This message was sent at your request.

For work with the project "#Application.ApplicationName#",

you are registered E-Mail address(Login): #Verification.EMail_User#

with the password: '#Password#

Best wishes. </CFMAIL> </CFIF> <CFELSE>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=login.cfm"> </CFIF>

Здесь в первую очередь анализируется наличие пользователя с введенным электронным адресом, после чего при успешном результате поиска расшифровывается пароль этого пользователя с указанием необходимого ключа. А уж следующим шагом отправляется письмо по указанному адресу с вложением в текст письма результата расшифровки.

Данный пример отправления пароля (sendpassword.cfm) полностью представлен в листинге П2.8 приложения 2.

Если вести речь о шифровании паролей, то в ColdFusion также представлена функция Hash, позволяющая конвертировать текст в 32-битный код по одностороннему алгоритму MDS. Применение данной функции уже не позволит нам передавать пароли забывчивым пользователям, однако и не во всех системах это требуется. Например, можно поступить так:

<CFQUERY NAME="AddUser" DATASOURCE="#Application.dsn#">

INSERT INTO UserMail(EMail_User, FirstN_User, LastN_User, Pass_User, DateSignUp_User, LastLogin_User,

LastIP_User, LastBrowser_User, TotalLogins__User)

VALUES('#EMail_User#', '#Form.FirstN_User#',

'#Form.LastN_User#', '#Hash(Form.Pass_User)#',

'#DateNow#, '#DateNow#',

'#CGI.REMOTE_ADDR#', '#CCI.HTTP_USER_AGENT#',

1) </CFQUERY>

где вместо введенного пароля в базу данных благополучно записывается нeподдающийся расшифровке результат функции Hash

В данном случае уже при идентификации пользователя введенный им пароль необходимо конвертировать с помощью все той же функции Наsh и затем полученный результат сравнивать со значением, находящимся в базе данных в качестве пароля. При этом идентификацию можно считать удачной, если сравниваемые значения окажутся идентичными.

Адресная книга

Что собой представляет адресная книга? При формировании тех или иных почтовых сообщений всегда присутствует понятие адресатов, т. е. "объектов внимания", которым, собственно говоря, вы и адресуете свои лирические послания и от которых могут приходить ответные сообщения. Более того, достаточно часто приходится отправлять электронные письма одним и тем же адресатам, и в этой связи с точки зрения пользователя было бы удобно выбирать электронный адрес получателя из существующего списка, вместо того, чтобы каждый раз набирать его адрес заново. Для решения данной задачи многие разработчики почтовых систем реализуют адресную книгу, позволяющую пользователям формировать список часто используемых электронных адресов. Причем в соответствии с электронным адресом следует хранить дополнительные данные, позволяющие охарактеризовать тот или иной вновь добавленный адресат или, можно назвать иначе, контакт. Создавая сложную по структуре адресную книгу, необходимо предусмотреть возможность объединения контактов в определенные группы, мы же облегчим себе задачу, реализуя простую адресную книгу, куда будут включены помимо электронного адреса (e-mail) такие поля, как:

В связи с тем, что адресная книга может разрастись до "немыслимых" размеров, Web-страница, отображающая список контактов, разделена на блоки. В нашем случае каждый блок содержит по семь контактов, однако данное значение можно регулировать. Для этой цели в конфигурационный файл (Application.cfm) данного приложения включена переменная Application.pageRows. Также в конфигурационный файл приложения добавлена переменная Application.MaxLinePages, позволяющая регулировать количество данных блоков, располагаемых на одной линии. Изначально это значение равняется 12. Более подробно о настройке конфигурационных файлов читайте в главе 10.

В разработанной нами адресной книге имеется дополнительная колонка под названием Controls (Управление), где напротив каждого контакта располагаются два элемента в виде графических изображений: Edit (Редактировать) и Delete (Удалить), позволяющие соответственно редактировать и удалять данный контакт. В нижней же части управляющей колонки находится элемент Delete Selected (Удалить выделенные), предназначенный для группового удаления контактов, предварительно выделенных с помощью вспомогательных элементов Select All (Выделить все), Unselect All (Отмена выделения для всех) или Invert Checks (Обратить отмеченные), расположенных в нижней части Web-страницы. Для добавления нового контакта достаточно нажать кнопку New Contact (Новый контакт) и заполнить предлагаемые поля.

Каждый электронный адрес контакта, расположенный в колонке. EMail (e-mail), является ссылкой, при щелчке по которой открывается страница NewMail.cfm, предназначенная для создания нового почтового сообщения с автоматически заполненным полем То (Кому), где значением поля является выбранный электронный адрес. Если же существует необходимость создать почтовое сообщение сразу для нескольких адресатов, достаточно, отметив таковые либо вручную, либо при помощи все тех же вспомогательных инструментов группового выделения, нажать кнопку New Mail for Selected (Новое сообщение для выделенных контактов).

Так вот эти инструменты предполагается использовать для сортировки списка контактов как по возрастанию, так и по убыванию в соответствии с направлением стрелок. Причем изначально список отсортирован по возрастанию первого имени (First) адресата.

Мы уже говорили о возможно большом количестве контактов, для чего данный список разделяется на страничные блоки. Впрочем, иногда пользователю требуется найти конкретный адрес по ключевому слову, не прибегая к поблочному перелистыванию. И для этой цели мы включили два элемента: поле для ввода искомых фрагментов текста и кнопку Search (Поиск), для выполнения поиска. К примеру, введем в поле ввода символ ь и выполним поиск.

Как видно из рисунка, были найдены две записи, где цветом выделены поля, включающие искомый фрагмент текста. Обратите внимание, что при поиске игнорируется разница между верхним и нижним регистрами.

Создание и отправление почтовых сообщении

Скажем несколько слов о создании почтовых сообщений. Уже было отмечено, что в нашем примере за создание писем отвечает Web-страница NewMail.cfm. На этой странице представлена форма для заполнения необходимых данных, подкрепленная ссылками для полей, требующих ввод электронного адреса: поле То (Кому), поле Сс (Точная копия) и поле Вcс (Слепая точная копия). Эти ссылки предусмотрены для вызова списка электронных адресов из заранее сформированной адресной книги, о которой уже достаточно много было сказано.

В режиме составления писем можно устанавливать тип письма (Туре) либо в виде простого текста (переключатель plain text), либо в виде HTML (переключатель html). Также в нашей почтовой службе предусмотрена возможность прикрепления к письму до трех файлов различного формата.

Заметим, что помимо отправления письма с помощью нажатия кнопки Send (Отправить) есть возможность сохранить составленное письмо в разделе черновиков, используя при этом кнопку Save Draft (Сохранить как черновик). Таким образом, сохраненное письмо в виде черновика в любой момент можно предварительно просмотреть, отредактировать или отправить по указанному адресу.

Просмотр папок с письмами

Если лицо, являющееся получателем составленного нами письма, также пользуется данной почтовой службой, то при входе в систему он или она, к примеру, может наблюдать следующую картину.

Важно подчеркнуть, что в этом случае количество новых писем складывается из входящих с POP-сервера и непрочитанных, но хранящихся в базе данных. Причем, как только система обнаруживает новые письма на РОР-сервере, эти письма тут же добавляются в базу данных со свойством "не прочитано", и затем POP-сервер освобождается от них. Непрочитанные же письма выделяются жирным шрифтом.

Как видно для писем так же, как и для адресной книги, предусмотрен инструмент поиска, действующий по той же схеме. Также здесь имеется колонка управления Controls (Управление), составленная из следующих элементов в виде графических изображений:

При всем при том, элемент Delete (Удалить) письма, находящиеся в папках Inbox (Входящие) и Junk (Хлам), перемещает в папку Deleted (Удаленные).

По отношению к другим папкам элемент Delete (Удалить) безвозвратно удаляет письма из базы данных.

Для удобства здесь же имеется возможность вернуться обратно к списку входящих писем. Используя элементы перемещения от письма к письму в виде четырех разнонаправленных стрелок, расположенных в правом верхнем углу текущей Web-страницы, можно просматривать другие письма. Также здесь дублируются элементы управления, перечисленные выше. К примеру, если после просмотра полученного письма вы решили немедленно отправить ответ на него, то это можно сделать при помощи элемента Reply (Ответить), аргументом для которого будет являться уникальный код письма.

Что же касается вложенных файлов, то они располагаются списком в виде ссылок, позволяющих открывать данные файлы.

И последнее в отношении просмотра писем: любое входящее письмо имеет подробный заголовок, не всегда желанный для чтения. И по этой причине на странице просмотра мы добавили кнопку Properties (Свойства), позволяющую открывать текст подробного заголовка в отдельном окне. При этом за содержание свойств текущего письма отвечает страница Properties_Mail.cfm. Данный заголовок мы также используем для анализа типа входящих писем. При существовании в заголовке входящего письма фрагмента "Content-type: text/html" данное письмо помещается в базу данных с отметкой "HTML", что позволяет регулировать вид просмотра при чтении писем. К примеру:

<CFQUERY NAME="SaveMail" DATASOURCE="#Application.dsn#">

<CFIF FindNoCaset'Content-type: text/html', Header) gt 0>

<CFSET conType = "HTML">

<CFELSE>

<CFSET conType = ""> </CFIF>

INSERT INTO MailBox(Key_User, Key_TypeBox, To_Box, From_Box, Cc_Box, Subject_Box, Body_Box, ReplyTo_Box, Type_Box, Date_Box, ReadState_Box, Header_Box, Attachments_Box, AttachmentFiles_Box) VALUES(#Session.user.id#, 1, '#To#', '#From#',

'#Cc#', '#Subject#', 'tBodyl', '#Replyto#', '#conType#', '#Date_#', 0, '#Header#', '#Attachments#', '#Attachmentfiles#')

</CFQUERY>

Список исходящих писем только тем и отличается от списка входящих, что для исходящих реализована колонка То (Кому), а для входящих писем отображается колонка From (От кого). И как уже было отмечено, при удалении входящей почты письма перемещаются в папку Deleted (Удаленные), а подобное действие, совершаемое по отношению к исходящей почте, приводит к удалению писем из базы данных.

Для почты, расположенной в папке удаленных писем, характерно, что данные письма всегда можно восстановить. И для этой цели добавлен управляющий элемент Undo (Восстановить). Если, конечно, перед этим не была выполнена команда очистки писем, помеченных на удаление — Empty Deleted (Опустошить помеченные на удаление).

Письма, находящиеся в папке Draft (Черновик), по сути можно рассматривать как сформированные, но отложенные для отправки на некоторый неопределенный срок. Это достаточно удобно, когда следует заранее написать ряд писем и отправить их только через некоторое время. При этом, имея возможность пересмотреть содержимое данных писем, либо вообще отказаться от отправления таковых.

Письма, находящиеся в папке Junk (Хлам), так же, как и письма, помеченные на удаление, можно восстановить. То есть все восстановленные письма будут перемещены обратно в папку Inbox (Входящие).

Заключение по реализации почтового ящика

Конечно, можно было бы пойти дальше, предоставив потенциальному пользователю дополнительные возможности, такие как: управление папками, группировка контактных лиц, возможность обмениваться контактами, создание учетных записей для чтения писем из нескольких почтовых ящиков, проверка правописания, вставка ссылок, форматирование текста, возможность автоматической перекодировки, использование шаблонов, установка фильтров и т. д.

Однако представленный в этой главе пример реализации почтового ящика был создай в достаточно короткие сроки и не рассматривается как идеальный продукт. Целью же программирования данной системы является демонстрация возможностей ColdFusion Server.

В приложении 2 представлены коды файлов в рамках проекта "MyMail".

Резюме

Подведем итог. В данной главе мы использовали CFML-теги <CFMAIL>, <CFMAILPARAM>, <CFPOP> и CFML-функции ParseDateTime, Chr, Encrypt, Decrypt, Hash.